<?php

use App\Constants\ErrorCode;
use App\Exception\ApiException;
use App\Log;
use Hyperf\Context\ApplicationContext;
use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ServerRequestInterface;
use function Hyperf\Support\env;

if (!function_exists('remove_dir')) {
    /**递归删除目录下的所有文件和子目录
     * @param $dir
     * @return bool
     */
    function remove_dir($dir): bool
    {
        // 检查目录是否存在
        if (!is_dir($dir)) {
            return false;
        }

        // 打开目录
        $it    = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
        $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);

        // 遍历目录中的所有文件和子目录
        foreach ($files as $file) {
            if ($file->isDir()) {
                rmdir($file->getRealPath());
            } else {
                unlink($file->getRealPath());
            }
        }

        return rmdir($dir);
    }
}

if (!function_exists('throw_error')) {
    /**抛出异常
     * @param string|null $msg
     * @param int $code
     * @param \Throwable|null $previous
     * @return void
     */
    function throw_error(?string $msg, ErrorCode|int $code = ErrorCode::FAIL, Throwable $previous = null): void
    {
        throw new ApiException($code, $msg, $previous);
    }
}

if (!function_exists('throw_error_if')) {
    /**
     * @param bool $condition
     * @param string|null $msg
     * @param int $code
     * @param \Throwable|null $previous
     * @return void
     */
    function throw_error_if(
        bool      $condition,
        ?string   $msg,
        ErrorCode $code = ErrorCode::FAIL,
        Throwable $previous = null
    ): void
    {
        if (!$condition) {
            return;
        }

        throw_error($msg, $code, $previous);
    }
}

if (!function_exists('format_bytes')) {
    /**
     * 格式化文件大小
     * @param $size
     * @return string
     */
    function format_bytes($size): string
    {
        $units = array(' B', ' KB', ' MB', ' GB', ' TB');

        for ($i = 0; $size >= 1024 && $i < 4; $i++) {
            $size /= 1024;

        }
        return round($size, 2) . $units[$i];
    }
}

if (!function_exists("container")) {
    /**
     * @return \Psr\Container\ContainerInterface
     */
    function container(): ContainerInterface
    {
        return ApplicationContext::getContainer();
    }
}

if (!function_exists("stdout_log")) {
    /**公屏打印日志
     * @return \Hyperf\Contract\StdoutLoggerInterface
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    function stdout_log(): StdoutLoggerInterface
    {
        return container()->get(StdoutLoggerInterface::class);
    }
}

if (!function_exists('event_trigger')) {
    /**
     * @param object $dispatch
     * @return object
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    function event_trigger(object $dispatch): object
    {
        return container()->get(EventDispatcherInterface::class)->dispatch($dispatch);
    }
}

if (!function_exists("request")) {
    /**
     * @return mixed|\Psr\Http\Message\ServerRequestInterface
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    function request()
    {
        return container()->get(ServerRequestInterface::class);
    }
}

if (!function_exists("get_real_ip")) {
    /**
     * @return string
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    function get_real_ip(): string
    {
        if ($ip = request()->getHeaderLine('x-real-ip')) {
            return $ip;
        } else {
            if ($ip = request()->getHeaderLine('x-forwarded-for')) {
                return $ip;
            }
        }

        return request()->getServerParams()['remote_addr'] ?? '';
    }
}

/**
 * 获取设备标识符
 * @return string
 * @throws \Psr\Container\ContainerExceptionInterface
 * @throws \Psr\Container\NotFoundExceptionInterface
 */
function get_device_identifier(): string
{
    return request()->getHeaderLine('x-device-id') ?? '';
}

if (!function_exists("is_prod")) {
    /**判断是否是生产环境
     * @return bool
     */
    function is_prod(): bool
    {
        return env('APP_ENV') === 'prod';
    }
}

if (!function_exists('var_dump_orlog')) {
    function var_dump_orlog($str, $scene = '')
    {

        if (is_prod()) {
            Log::get('log', 'task')->info("{$scene}->" . $str);
        } else {
            var_dump("{$scene}->$str");
        }
    }
}

if (!function_exists("measure_execution_time")) {
    /**
     * 计算代码片段执行时间并打印
     * @param $callback
     * @param string $description
     * @return void
     */
    function measure_execution_time($callback, string $description = 'Code snippet')
    {
        // 获取开始时间戳
        $startTime = microtime(true);

        // 执行传入的回调函数
        $callback();

        // 获取结束时间戳
        $endTime = microtime(true);

        // 计算执行时间（秒）
        $executionTime = $endTime - $startTime;

        // 打印描述和执行时间
        var_dump("$description executed in $executionTime seconds.\n");
    }
}

if (!function_exists("format_error")) {
    function format_error(Throwable $throwable): array
    {
        return [
            'message' => $throwable->getMessage(),
            'code'    => $throwable->getCode(),
            'file'    => $throwable->getFile(),
            'line'    => $throwable->getLine(),
            'trace'   => $throwable->getTraceAsString(),
        ];
    }
}